#include <ctype.h>
#include <string.h>

const char *GetMimeType(const char *zName, int nName)
{
    const char *z;
    int i;
    int first, last;
    int len;
    int max_len = 7;

    /* A table of mimetypes based on file suffixes. 
    ** Suffixes must be in sorted order so that we can do a binary
    ** search to find the mime-type
    */
    static const struct
    {
        const char zSuffix[sizeof(__uint128_t)];  /* The file suffix */
        const char *zMimetype;                    /* The corresponding mimetype */
    } aMime[] = {
        {"c", "text/plain"},
        {"f", "text/plain"},
        {"h", "text/plain"},
        {"m", "text/plain"},
        {"t", "application/x-troff"},
        {"ra", "audio/x-realaudio"},
        {"cc", "text/plain"},
        {"nc", "application/x-netcdf"},
        {"me", "application/x-troff-me"},
        {"hh", "text/plain"},
        {"sh", "application/x-sh"},
        {"ai", "application/postscript"},
        {"dl", "video/dl"},
        {"gl", "video/gl"},
        {"pl", "application/x-perl"},
        {"pm", "application/x-perl"},
        {"rm", "audio/x-pn-realaudio"},
        {"tr", "application/x-troff"},
        {"js", "application/x-javascript"},
        {"ms", "application/x-troff-ms"},
        {"ps", "application/postscript"},
        {"qt", "video/quicktime"},
        {"au", "audio/ulaw"},
        {"ez", "application/andrew-inset"},
        {"gz", "application/x-gzip"},
        {"f90", "text/plain"},
        {"mp2", "video/mpeg"},
        {"mp2", "audio/mpeg"},
        {"mp3", "audio/mpeg"},
        {"oda", "application/oda"},
        {"vda", "application/vda"},
        {"lha", "application/octet-stream"},
        {"wma", "audio/x-ms-wma"},
        {"pdb", "chemical/x-pdb"},
        {"deb", "application/x-debian-package"},
        {"rgb", "image/x-rgb"},
        {"xlc", "application/vnd.ms-excel"},
        {"doc", "application/msword"},
        {"src", "application/x-wais-source"},
        {"asc", "text/plain"},
        {"jad", "text/vnd.sun.j2me.app-descriptor"},
        {"vcd", "application/x-cdlink"},
        {"mid", "audio/midi"},
        {"skd", "application/x-koan"},
        {"snd", "audio/basic"},
        {"cod", "application/vnd.rim.cod"},
        {"xwd", "image/x-xwindowdump"},
        {"ice", "x-conference/x-cooltalk"},
        {"jpe", "image/jpeg"},
        {"mpe", "video/mpeg"},
        {"pre", "application/x-freelance"},
        {"exe", "application/octet-stream"},
        {"cdf", "application/x-netcdf"},
        {"hdf", "application/x-hdf"},
        {"pdf", "application/pdf"},
        {"ief", "image/ief"},
        {"aif", "audio/x-aiff"},
        {"gif", "image/gif"},
        {"mif", "application/x-mif"},
        {"tif", "image/tiff"},
        {"asf", "video/x-ms-asf"},
        {"rtf", "application/rtf"},
        {"rtf", "text/rtf"},
        {"swf", "application/x-shockwave-flash"},
        {"dxf", "application/dxf"},
        {"ogg", "application/ogg"},
        {"png", "image/png"},
        {"jpg", "image/jpeg"},
        {"mpg", "video/mpeg"},
        {"svg", "image/svg+xml"},
        {"dwg", "application/acad"},
        {"csh", "application/x-csh"},
        {"msh", "model/mesh"},
        {"lzh", "application/octet-stream"},
        {"fli", "video/fli"},
        {"smi", "application/smil"},
        {"tsi", "audio/TSP-audio"},
        {"avi", "video/x-msvideo"},
        {"dvi", "application/x-dvi"},
        {"arj", "application/x-arj-compressed"},
        {"tcl", "application/x-tcl"},
        {"xll", "application/vnd.ms-excel"},
        {"xml", "text/xml"},
        {"sol", "application/solids"},
        {"spl", "application/x-futuresplash"},
        {"wrl", "model/vrml"},
        {"stl", "application/SLA"},
        {"ram", "audio/x-pn-realaudio"},
        {"pbm", "image/x-portable-bitmap"},
        {"xbm", "image/x-xbitmap"},
        {"scm", "application/x-lotusscreencam"},
        {"ogm", "application/ogg"},
        {"pgm", "image/x-portable-graymap"},
        {"sgm", "text/sgml"},
        {"skm", "application/x-koan"},
        {"xlm", "application/vnd.ms-excel"},
        {"pnm", "image/x-portable-anymap"},
        {"com", "application/x-msdos-program"},
        {"ppm", "image/x-portable-pixmap"},
        {"rpm", "audio/x-pn-realaudio-plugin"},
        {"xpm", "image/x-xpixmap"},
        {"htm", "text/html"},
        {"man", "application/x-troff-man"},
        {"pgn", "application/x-chess-pgn"},
        {"bin", "application/octet-stream"},
        {"pgp", "application/pgp"},
        {"zip", "application/zip"},
        {"skp", "application/x-koan"},
        {"lsp", "application/x-lisp"},
        {"tsp", "application/dsptype"},
        {"stp", "application/STEP"},
        {"jar", "application/java-archive"},
        {"kar", "audio/midi"},
        {"rar", "application/x-rar-compressed"},
        {"tar", "application/x-tar"},
        {"dcr", "application/x-director"},
        {"dir", "application/x-director"},
        {"dxr", "application/x-director"},
        {"ras", "image/cmu-raster"},
        {"ras", "image/x-cmu-raster"},
        {"igs", "model/iges"},
        {"xls", "application/vnd.ms-excel"},
        {"dms", "application/octet-stream"},
        {"eps", "application/postscript"},
        {"ips", "application/x-ipscript"},
        {"pps", "application/mspowerpoint"},
        {"css", "text/css"},
        {"bat", "application/x-msdos-program"},
        {"set", "application/set"},
        {"sit", "application/x-stuffit"},
        {"skt", "application/x-koan"},
        {"pot", "application/mspowerpoint"},
        {"cpt", "application/mac-compactpro"},
        {"ppt", "application/mspowerpoint"},
        {"prt", "application/pro_eng"},
        {"txt", "text/plain"},
        {"m3u", "audio/x-mpegurl"},
        {"wav", "audio/x-wav"},
        {"viv", "video/vnd.vivo"},
        {"flv", "video/flv"},
        {"wmv", "video/x-ms-wmv"},
        {"unv", "application/i-deas"},
        {"mov", "video/quicktime"},
        {"tsv", "text/tab-separated-values"},
        {"xlw", "application/vnd.ms-excel"},
        {"drw", "application/drafting"},
        {"wax", "audio/x-ms-wax"},
        {"tex", "application/x-tex"},
        {"wmx", "video/x-ms-wmx"},
        {"ipx", "application/x-ipix"},
        {"hqx", "application/mac-binhex40"},
        {"asx", "video/x-ms-asx"},
        {"etx", "text/x-setext"},
        {"rtx", "text/richtext"},
        {"wvx", "video/x-ms-wvx"},
        {"tgz", "application/x-tar-gz"},
        {"ppz", "application/mspowerpoint"},
        {"xyz", "chemical/x-pdb"},
        {"mpga", "audio/mpeg"},
        {"aifc", "audio/x-aiff"},
        {"ccad", "application/clariscad"},
        {"mime", "www/mime"},
        {"aiff", "audio/x-aiff"},
        {"tiff", "image/tiff"},
        {"roff", "application/x-troff"},
        {"jpeg", "image/jpeg"},
        {"mpeg", "video/mpeg"},
        {"mesh", "model/mesh"},
        {"midi", "audio/midi"},
        {"wiki", "application/x-fossil-wiki"},
        {"texi", "application/x-texinfo"},
        {"smil", "application/smil"},
        {"sgml", "text/sgml"},
        {"vrml", "model/vrml"},
        {"html", "text/html"},
        {"cpio", "application/x-cpio"},
        {"silo", "model/mesh"},
        {"vivo", "video/vnd.vivo"},
        {"step", "application/STEP"},
        {"shar", "application/x-shar"},
        {"gtar", "application/x-gtar"},
        {"iges", "model/iges"},
        {"vsix", "application/vsix"},
        {"movie", "video/x-sgi-movie"},
        {"bcpio", "application/x-bcpio"},
        {"ustar", "application/x-ustar"},
        {"class", "application/octet-stream"},
        {"latex", "application/x-latex"},
        {"sv4crc", "application/x-sv4crc"},
        {"texinfo", "application/x-texinfo"},
        {"sv4cpio", "application/x-sv4cpio"}
    };

    len = 0;
    for(z = zName + nName - 1; z != zName && *z != '.'; z--)
        len++;

    if(*z++ == '.' && len <= max_len)
    {
        char zSuffix[sizeof(__uint128_t)] = { };
        for(int j = 0; *z; j++)
            zSuffix[j] = tolower(*z++);

        first = 0;
        last = sizeof(aMime)/sizeof(aMime[0]);

        do {
            i = (first + last) / 2;

            //printf("%d %d %d\n",first,last,i);

            if(*((__uint128_t*)(aMime[i].zSuffix)) == *((__uint128_t*)zSuffix))
                return aMime[i].zMimetype;
            else
            {
                if(*((__uint128_t*)(aMime[i].zSuffix)) > *((__uint128_t*)zSuffix))
                    last = i - 1;
                else
                    first = i + 1;
            }
        } while(first <= last);
    }

    return "application/octet-stream";
}
